The SignalWire Client
The SignalWire Client provides access to SignalWire's services on the browser. It provides methods to handle incoming calls, dial to addresses and to register devices for notifications.
Instantiation
The SignalWire client is instantiated using the SignalWire
function.
If you're including the @signalwire/js
dependency as a script in HTML,
the SignalWire
function is a property of the SignalWire
global variable
that the script sets. So you would call it as
window.SignalWire.SignalWire( ...params)
(or simply SignalWire.SignalWire
).
<script type="text/javascript" src="https://unpkg.com/@signalwire/js@dev"></script>
<script>
async function main() {
const client = await SignalWire.SignalWire({
token: "<TOKEN>",
});
}
</script>
If you installed @signalwire/js
from npm, use it as follows:
import { SignalWire } from "@signalwire/js";
async function main() {
const client = await SignalWire({
token: "<TOKEN>",
});
}
If you want to use it in a React or a React Native project, we also have a community library
which takes care of the React-specific implementation details. You can use the
library directly by installing the @signalwire-community/react
(for React)
and the @signalwire-community/react-native
(for React native) from npm.
import { useSignalWire } from "@signalwire-community/react";
export default function App() {
const client = useSignalWire({
token: "<TOKEN>",
});
}
Parameters
▸ SignalWire(options
): Promise<SignalWireContract>
Name | Type | Required? | Description |
---|---|---|---|
options.token | string | Required | The project UUID of your SignalWire project (for billing and logging purposes). |
options.rootElement | HTMLElement | Optional | The HTML container element where the SDK will display the video stream. |
options.onRefreshToken | function | undefined | Optional | A function that gets called when the current token is about to expire (so you can get a new one via the OAuth2 refresh token mechanism) |
options.host | string | Optional | Set the domain which points to the SignalWire instance that you need to use |
options.disableUdpIceServers | boolean | Optional | Disable ICE UDP transport policy |
Example
The following code in demonstrate how you can instantiate a SignalWire client.
The token
is received through one of the Authentication
mechanisms discussed above.
- Vanilla JS
- React (community)
<html>
<body>
<script type="text/javascript" src="https://unpkg.com/@signalwire/js@dev"></script>
<script>
async function main() {
const client = await SignalWire.SignalWire({
host: "puc.signalwire.com",
token: "<TOKEN>",
});
const conversations = await client.conversation.getConversations();
console.log(conversations);
const addresses = await client.address.getAddresses();
console.log(addresses);
}
main();
</script>
</body>
</html>
import { useSignalWire } from "@signalwire-community/react";
// If you were using React Native, you'd import the same hook from
// the package `@signalwire-community/react-native`. Like so:
// import { useSignalWire } from "@signalwire-community/react-native";
import { useEffect } from "react";
export default function App() {
const client = useSignalWire({
host: "puc.signalwire.com",
token: "<TOKEN>",
});
useEffect(() => {
if (!client) return; // client is not initialized yet
async function log() {
const conversations = await client.conversation.getConversations();
console.log(conversations);
const addresses = await client.address.getAddresses();
console.log(addresses);
}
log(); //useEffect doesn't directly support async effects; thus a subfunction
}, [client]);
return <></>;
}
Methods
dial
▸ dial({to: string, nodeId ?: string}
): Promise<Call>
Dials to the address specified in the to
parameter, and returns a Call
object if successful.
If the rootElement
was set during client instantiation,
the video call will be injected into that container. Or rootElement
can be passed as a parameter
to dial
.
Parameters
Name | Type | Description |
---|---|---|
to | string | The address of the subscriber to dial (like /private/user1 ) |
rootElement | HTMLElement | The HTML container element to inject the Call into. |
Returns
Promise to a Call object that describes the ongoing call, and provides handles for controlling it.
online
▸ online(options
): Promise<Call>
Set the client to be online so it can receive call invites via WebRTC. The call invites can be accepted or rejected as per user input.
Parameters
Name | Type | Description |
---|---|---|
options | object | |
options.incomingCallHandlers | object | |
incomingCallHandlers.all? | function | Handler function for incoming calls via websocket and push notifications. |
incomingCallHandlers.websocket? | function | Handler function for incoming calls via websocket. |
incomingCallHandlers.pushNotification? | function | Handler function for incoming calls via push notifications. |
Response
TODO: Document Call object
Example
// Receive calls using push notifications
client.online({
incomingCallHandlers: {
all: __incomingCallHandler
},
})
// Function to handle the incoming call notification and stores the invite
window.__incomingCallHandler = (notification) => {
if (
!window.__invite ||
window.__invite.details.callID !== notification.invite.details.callID
) {
// Store call invite
window.__invite = notification.invite
}
// Trigger UI update here to convey the ringing state
}
// Function to answer the call
window.answer = async () => {
// Accept the call invite
const call = await window.__invite.accept({
rootElement: document.getElementById('rootElement'),
})
// Trigger UI update here to convey the connected state
}
// Function to reject the call
window.reject = async () => {
await window.__invite.reject()
// Trigger UI update here to convey the ready state
}
offline
▸ offline(): void
Set the client to be offline so it doesn't receive call invites via WebRTC.
sendMessage
▸ sendMessage(options
): Promise<Conversation>
- See Conversation for more details.
Send a Chat Message to a given Address ID. If no Conversation exists with that Address ID, one will be created.
Parameters
Name | Type | Description |
---|---|---|
options | object | |
options.addressId | string | The ID of the Address where to send the message. |
options.text | string | The Message text content. |
options.metadata? | object | Metadata to go along with the Message. |
options.details? | object | Extra Message event details. Can be used to construct custom UIs, for example. |
Example
await client.sendMessage({
addressId: "12345",
text: "Hello from SignalWire!"
});
httpHost
▸ httpHost(): string
Returns the URL of the host that the client will use to make HTTP requests (like querying the list of addresses or conversations).
Parameters
None
Returns
string
Example
console.log(client.httpHost());
// fabric.signalwire.com
registerDevice
▸ registerDevice(options
): Promise<
Response
>
Register a device for receiving SignalWire notifications related to the registering subscriber.
Parameters
Name | Type | Description |
---|---|---|
options | object | |
options.deviceToken | string | The token you receive from the device after getting notification permission from the user. |
options.deviceType | "iOS" | "Android" | "Desktop" | The address type to filter for. Possible values: subscriber , room , app , call . |
Response for RegisterDevice (JSON)
The method call returns a promise to a JSON object with the following fields:
Name | Type | Description |
---|---|---|
id | string | ID of the current device registration. Use this when sending a request to unregister this device. |
device_token | string | Echo of theoptions.deviceToken option that was sent while registering. |
device_type | "iOS" | "Android" | "Desktop" | Echo of the options.deviceType option that was sent while registering. |
device_name | null | Not yet implemented |
push_notification_key | string | SignalWire only sends encrypted push notifications. When you receive them, use this key to decode them (Details) |
date_registered | string | The date string when the server registered this device |
Example
await client.registerDevice({ deviceToken: "XYZ", deviceType: "Desktop" });
// {
// "id": "222rr8b2-9070-4383-af17-e48b97e900a0",
// "device_token": "XYZ",
// "device_name": null,
// "device_type": "Desktop",
// "push_notification_key": "qMdif...fZzz",
// "date_registered": "2024-02-27T12:46:42Z"
// }
unregisterDevice
▸ registerDevice({id:string}
): Promise<{}>
Cancels the registration of the device mentioned by its ID.
Parameters
Name | Type | Description |
---|---|---|
id | string | The ID of the device that you need to unregister. This ID is returned when registering the device. |
Returns
Returns empty object when successful. Throws error with the server's error when unsuccessful.
Example
const device = await client.registerDevice({ deviceToken: "XYZ", deviceType: "Desktop" });
// commit `device.id` and `device.push_notification_key` to a persistent storage like localStorage or session or file
// ...
// When the time comes to "log out" or stop getting notifications:
await client.unregisterDevice({ id: device.id });
connect
▸ connect()
Connects to the WebSocket client. SignalWire manages the WebSocket connection
automatically in most cases, so you'll only need to use connect
in the rare edge
cases when you need to manually manage the connection.
disconnect
▸ disconnect()
Disconnects from the WebSocket client. SignalWire manages the WebSocket connection automatically in most cases.
Returns
Nothing
handlePushNotification
▸ handlePushNotification(payload
): Promise<Call>
Creates the call based on the push notification that the device received.
Dials to the address specified in the to
parameter, and returns a Call
object if successful.
If the rootElement
was set during client instantiation,
the video call will be injected into that container.
Parameters
Name | Type | Description |
---|---|---|
payload | object | The contents of the push notification |
The exact format of Push Notification you receive will vary depending from Android to iOS to Web. But it will always contain the following information:
Name | Type | Description |
---|---|---|
encryption_type | string | Type of encryption used ('aes_256_gcm' or 'none' ) |
notification_uuid | string | UUID of the push notification |
with_video | string | Indicates whether the call includes video ("true" | "false" ) |
incoming_caller_name | string | Name of the incoming caller |
incoming_caller_id | string | ID of the incoming caller |
invite | string | Invitation (base 64 encoded, compressed, and possibly encrypted) |
title | string | Title of the call |
type | string | Type of notification ('call_invite' ) |
iv | string | The initialization vector of the encryption (base 64) |
tag | string | The tag info for the encryption (base 64) |
version | string | The version of the push notification received |
In addition to this, you are required to add a decrypted
field which has the decrypted SDP invite.
To decrypt the encrypted invite, use the encryption key that was sent while calling registerDevice
method. The Push Notifications reference goes through this in detail.
Returns
Promise to a JavaScript object with the following attributes:
Name | Type | Description |
---|---|---|
resultType | string | a resultType of "inboundCall" signifies that a call was received |
resultObject | Call | The Call object |
Unlike with the dial
method, the Call
object here has not been started.
To accept and start the call, use Call.answer()
and to reject the call, use Call.hangup()
.
updateToken
▸ updateToken(token:string
): Promise<void>
Update the auth token being used by the client. For example, in case when the old token is about to expire and you have refreshed the token through OAuth2.
Parameters
Name | Type | Description |
---|---|---|
token | string | The new token that the client should start to use. |
Returns
Returns empty object when successful. Throws error with the server's error when unsuccessful.
Example
import { SignalWire } from "@signalwire/js";
async function main() {
const client = await SignalWire({
token: "<TOKEN>",
onRefreshToken: () => {
let newToken = refreshToken(); // this function should refresh token as per OAuth2 protocol
client.updateToken(newToken);
},
});
}